﻿using DeZhen.Core.Framework.Business.Ioc;
using DeZhen.Core.Framework.Config;
using DeZhen.Core.Framework.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DeZhen.Core.Framework.Platform
{
    [Service(ServiceLifetime.Singleton)]
    public class AutowiredPlatform : IAutowiredPlatform
    {
        IServiceProvider _serviceProvider;
        public AutowiredPlatform(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        public void Autowired(object service)
        {
            var serviceType = service.GetType();
            foreach (FieldInfo field in serviceType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                SetFieldInfo(service, field);
            }
            foreach (PropertyInfo property in serviceType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                SetPropertyInfo(service, property);
            }
        }
        private void SetFieldInfo(object service, FieldInfo field)
        {
            var autowiredAttr = field.GetCustomAttribute<AutowiredAttribute>();
            var valueAttr = field.GetCustomAttribute<ValueAttribute>();
            if (autowiredAttr == null && valueAttr == null)
            {
                return;
            }
            if (autowiredAttr != null)
            {
                string serviceId = autowiredAttr.Identifier;
                if (serviceId == null)
                {
                    field.SetValue(service, _serviceProvider.GetService(field.FieldType));
                    return;
                }
                field.SetValue(service, _serviceProvider.GetServices(field.FieldType).Where(d => d.GetType().GetCustomAttribute<ServiceAttribute>().Identifier == serviceId).FirstOrDefault());
                return;
            }
            Object obj = Activator.CreateInstance(field.FieldType);
            AppConfig.GetSection(valueAttr.ConfigKey).Bind(obj);
            field.SetValue(service, obj);
        }
        private void SetPropertyInfo(object service, PropertyInfo property)
        {
            var autowiredAttr = property.GetCustomAttribute<AutowiredAttribute>();
            var valueAttr = property.GetCustomAttribute<ValueAttribute>();
            if (autowiredAttr == null || valueAttr == null)
            {
                return;
            }
            if (autowiredAttr != null)
            {
                string serviceId = autowiredAttr.Identifier;
                if (serviceId == null)
                {
                    property.SetValue(service, _serviceProvider.GetService(property.PropertyType));
                    return;
                }
                property.SetValue(service, _serviceProvider.GetServices(property.PropertyType).Where(d => d.GetType().GetCustomAttribute<ServiceAttribute>().Identifier == serviceId).FirstOrDefault());
                return;
            }
            Object obj = Activator.CreateInstance(property.PropertyType);
            AppConfig.GetSection(valueAttr.ConfigKey).Bind(obj);
            property.SetValue(service, obj);
        }
    }
}
